<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    Promise测试
    <script>
        function isObject(val){ 
            return typeof val === 'object' && val !== null
        }
        function isFunction(val){ 
            return typeof val === 'function' 
        }
        function isThenAble(x){ 
            return isObject(x) || isFunction(x) && isFunction(x.then)
        }
        const rejectPromise = function(prom, reason){
            if(prom._state !== 'pending'){
                return
            }
            prom._state = 'rejected'
            prom._reason = reason
            flushHandlers(prom)
        } 
        const resolvePromise = function(prom, x){ 
            if(prom._state !== 'pending'){
                return
            }
            if(isThenAble(x)){
                //x 和 prom 是同一个对象
                if(x===prom){
                    rejectPromise(prom, new TypeError('Chaining cycle detected for promise #<MyPromiss>'))
                    return
                }
                // x是一个Promise, prom 吸收 x 状态
                queueMicrotask(()=>{
                    x.then(
                        data=>{
                            resolvePromise(prom, data)
                        },
                        err=>{
                            rejectPromise(prom, err)
                        }
                    )
                }) 
            }
            else{
                prom._state = 'fulfilled'
                prom._data = x
                flushHandlers(prom)
            }
        } 
        //处理后续的回调
        //将curPromise中的所有回调进行处理
        function flushHandlers(curProm){
            if(curProm._state === 'pending'){
                return
            }
            const settledHandlers = curProm._settledHandlers //取出所有的回调
            //将后续处理放到微队列
            queueMicrotask(()=>{
                // for(const handler of settledHandlers){
                while(settledHandlers.length){
                    const handler = settledHandlers.shift()
                    const { onFulfilled, onRejected, prom } = handler
                    //当前的promise完成,但完成的回调不是函数,则状态穿透
                    if(!isFunction(onFulfilled) && curProm._state === 'fulfilled'){
                        resolvePromise(prom, curProm._data)
                        continue
                    }
                    //当前的promise失败,但失败的回调不是函数,则状态穿透
                    if(!isFunction(onRejected) && curProm._state === 'rejected'){
                        rejectPromise(prom, curProm._data)
                        continue
                    }
                    let resoult
                    try{
                        if(curProm._state === 'fulfilled'){
                            resoult = onFulfilled(curProm._data)
                        }else{
                            resoult = onRejected(curProm._reason)
                        }

                    }
                    catch(e){
                        onRejected(prom, e)
                        continue
                    }
                    //回调函数运行成功
                    resolvePromise( prom, resoult )
                }
            })
        }

        class myPromise{
            _state = 'pending'  //pending fulfilled rejected
            _reason = undefined //Promise失败状态下的相关数据
            _data = undefined   //Promise完成状态下的相关数据
            _settledHandlers = []
            constructor(excutor){
                const resolve = (data)=>{
                    resolvePromise(this, data)
                }
                const reject = (err)=>{ 
                    rejectPromise(this, err)
                }
                excutor(resolve, reject)
            }
            then( onFulfilled, onRejected ){
                const prom = this
                this._settledHandlers.push({
                    onFulfilled, onRejected, prom
                })
                flushHandlers(prom)
                return prom
            }
        }
        

        const p = new myPromise((resolve, reject)=>{
            setTimeout(() => {
                resolve(new Promise(()=>{}))
            }, 1000);
        })
        p
            .then(res=>{
                console.log(11111,res);
                
            })
            .then(res=>{
                console.log(2222,res);
            })
        setTimeout(() => {
            console.log(p)
        }, 1000);
    </script>
</body>
</html>